package Operator;

import java.util.Arrays;
import java.util.Random;

import environment.IO;

public class Strategy {
	
	protected static double minimalCallCost = 0.10;
	protected static double minimalInsideCallCost = 0.05;
	protected static double minimalPlayCallCost = 0.69;
	
	protected static double minimalInsideSmsCost = 0.00;
	protected static double minimalSmsCost = 0.01;
	
	protected static Random r;
	
	public String lastStrategy = "";
	
	protected class customPriceList extends PriceList{

		public customPriceList(String name) {
			super(name);
		}
		
		public void setPrices(double regularCost, double playCost, double insideCost,
				double regularSms, double insideSms)
		{
			regularCallCost = regularCost;
			playCallCost = playCost;
			insideCallCost = insideCost;
			
			regularSmsCost = regularSms;
			insideSmsCost = insideSms;
		}
	}
	
	public PriceList higherPrices(PriceList currentPriceList, double [] bestPrices)
	{
		// init Random for this strategy change
		r = new Random(System.currentTimeMillis());
		
		customPriceList resultPrices = new customPriceList(currentPriceList.operatorName);
		
		double [] myPrices = currentPriceList.getPrices();
		resultPrices.setPrices(myPrices[0], myPrices[1], myPrices[2], myPrices[3], myPrices[4]);
		
		switch(r.nextInt(2))
		{
		case 0:
			resultPrices = ripOffGeneralStrategy(resultPrices, bestPrices);
			break;
			
		case 1:
			resultPrices = rifOffSpecialisedStrategy(resultPrices, bestPrices);
			break;
		}
		
		IO.operatorPrint(Arrays.toString(resultPrices.getPrices()), IO.INFO);
		
		return resultPrices;
	}
	
	public PriceList lowerPrices(PriceList currentPriceList, double [] bestPrices)
	{
		// init Random for this strategy change
		r = new Random(System.currentTimeMillis());
		
		customPriceList resultPrices = new customPriceList(currentPriceList.operatorName);
		
		double [] myPrices = currentPriceList.getPrices();
		resultPrices.setPrices(myPrices[0], myPrices[1], myPrices[2], myPrices[3], myPrices[4]);
		
		switch(r.nextInt(3))
		{
		case 0:
			resultPrices = beatBestStrategy(resultPrices, bestPrices);
			break;
		case 1:
			resultPrices = specialisedStrategy(resultPrices, bestPrices);
			break;
		case 2:
			resultPrices = desparateStrategy(resultPrices, bestPrices);
			break;
		}
		
		IO.operatorPrint(Arrays.toString(resultPrices.getPrices()), IO.INFO);
		
		return resultPrices;
	}
	
	/**
	 * Excel others in one of the 
	 * @param ourPrices
	 * @param bestPrices
	 * @return
	 */
	protected customPriceList rifOffSpecialisedStrategy(
			customPriceList ourPrices, 
			double [] bestPrices)
	{
		String target = "";
		
		double [] prices = ourPrices.getPrices();
		
		double regularCost = prices[0];
		double playCost = prices[1];
		double insideCost = prices[2];
		double regularSms = prices[3];
		double insideSms = prices[4];
		
		switch(r.nextInt(5))
		{
		case 0:
			regularCost = 12.5/10.0 * regularCost;
			target = "rozmów";
			break;
		case 1:
			playCost = 12.5/10.0 * playCost;
			target = "rozmów do play";
			break;
		case 2:
			insideCost = 12.5/10.0 * insideCost;
			target = "rozmów w sieci";
			break;
		case 3:
			regularSms = 12.5/10.0 * regularSms;
			target = "smsów";
			break;
		case 4:
			insideSms = 12.5/10.0 * insideSms;
			target = "smsów w sieci";
			break;
		}
		
		ourPrices.setPrices(regularCost, insideCost, playCost, regularSms, insideSms);
		IO.operatorPrint(ourPrices.operatorName + " używa strategii ripOffSpecialised. Podnosi ceny " + target + ".", IO.INFO);
		
		lastStrategy = "ripOffSpecialised " + target;
		
		return ourPrices;
	}
	
	/**
	 * Make all prices higher.
	 * @param ourPrices
	 * @return
	 */
	protected customPriceList ripOffGeneralStrategy(
			customPriceList ourPrices, 
			double [] bestPrices)
	{
		double [] prices = ourPrices.getPrices();
		
		double regularCost = 11.0/10.0 * prices[0];
		double playCost = 11.0/10.0 * prices[1];
		double insideCost = 11.0/10.0 * prices[2];
		double regularSms = 11.0/10.0 * prices[3];
		double insideSms = 11.0/10.0 * prices[4];
		
		ourPrices.setPrices(regularCost, playCost, insideCost, regularSms, insideSms);
		IO.operatorPrint(ourPrices.operatorName + " używa strategii ripOffGeneral", IO.INFO);
		

		lastStrategy = "ripOffGeneral";
		
		return ourPrices;
	}
	
	/**
	 * Higher only the prices which are the lowest on the market.
	 * @param ourPrices
	 * @param bestPrices
	 * @return
	 */
	protected customPriceList ripOffSmartStrategy(
			customPriceList ourPrices, 
			double [] bestPrices)
	{
		double [] prices = ourPrices.getPrices();
		
		double regularCost = prices[0];
		double playCost = prices[1];
		double insideCost = prices[2];
		double regularSms = prices[3];
		double insideSms = prices[4];
		
		if (regularCost == bestPrices[0])
			regularCost = 12.0/10.0 * regularCost;
		
		if (playCost == bestPrices[1])
			playCost = 12.0/10.0 * playCost;
		
		if (insideCost == bestPrices[2])
			insideCost = 12.0/10.0 * insideCost;
		
		if (regularSms == bestPrices[3])
			regularSms = 12.0/10.0 * regularSms;
		
		if (insideSms == bestPrices[4])
			insideSms = 12.0/10.0 * insideSms;
		
		ourPrices.setPrices(regularCost, playCost, insideCost, regularSms, insideSms);
		IO.operatorPrint(ourPrices.operatorName + " używa strategii ripOffSmart.", IO.INFO);
		

		lastStrategy = "ripOffSmart";
		
		return ourPrices;
	}
	
	/**
	 * Aggressive strategy: set prices which are higher than best
	 * to be half of the best operator and minimal.
	 * @param ourPrices
	 * @param bestPrices
	 * @return
	 */
	protected customPriceList beatBestStrategy(
			customPriceList ourPrices, 
			double [] bestPrices)
	{
		double [] prices = ourPrices.getPrices();
		
		double regularCost = prices[0];
		double playCost = prices[1];
		double insideCost = prices[2];
		double regularSms = prices[3];
		double insideSms = prices[4];
		
		if (regularCost > bestPrices[0])
			regularCost = (bestPrices[0] + minimalCallCost)/2.0;
		
		if (playCost > bestPrices[1])
			playCost = (bestPrices[1] + minimalPlayCallCost)/2.0;
		
		if (insideCost > bestPrices[2])
			insideCost = (bestPrices[2] + minimalInsideCallCost)/2.0;
		
		if (regularSms> bestPrices[3])
			regularSms = (bestPrices[3] + minimalSmsCost)/2.0;
		
		if (insideSms > bestPrices[4])
			insideSms = (bestPrices[4] + minimalInsideSmsCost)/2.0;
		
		ourPrices.setPrices(regularCost, playCost, insideCost, regularSms, insideSms);
		IO.operatorPrint(ourPrices.operatorName + " używa strategii beatBest.", IO.INFO);
		

		lastStrategy = "beatBest";
		return ourPrices;
	}
	
	/**
	 * Desperate strategy: set all prices to be 3/4 of the best operator and minimal.
	 * @param ourPrices
	 * @param bestPrices
	 * @return
	 */
	protected customPriceList desparateStrategy(
			customPriceList ourPrices, 
			double [] bestPrices)
	{
		double [] prices = ourPrices.getPrices();
		
		double regularCost = prices[0];
		double playCost = prices[1];
		double insideCost = prices[2];
		double regularSms = prices[3];
		double insideSms = prices[4];
		
		regularCost = 3.0*(bestPrices[0] + minimalCallCost)/8.0;
		playCost = 3.0*(bestPrices[1] + minimalPlayCallCost)/8.0;
		insideCost = 3.0*(bestPrices[2] + minimalInsideCallCost)/8.0;
		regularSms = 3.0*(bestPrices[3] + minimalSmsCost)/8.0;
		insideSms = 3.0*(bestPrices[4] + minimalInsideSmsCost)/8.0;
		
		ourPrices.setPrices(regularCost, playCost, insideCost, regularSms, insideSms);
		IO.operatorPrint(ourPrices.operatorName + " używa strategii desperate.", IO.INFO);

		lastStrategy = "desperate";
		return ourPrices;
	}
	
	/**
	 * Excel others in one of the 
	 * @param ourPrices
	 * @param bestPrices
	 * @return
	 */
	protected customPriceList specialisedStrategy(
			customPriceList ourPrices, 
			double [] bestPrices)
	{
		String target = "";
		
		double [] prices = ourPrices.getPrices();
		
		double regularCost = prices[0];
		double playCost = prices[1];
		double insideCost = prices[2];
		double regularSms = prices[3];
		double insideSms = prices[4];
		
		dupa:
		switch(r.nextInt(5))
		{
		case 0:
			regularCost = (bestPrices[0] + minimalCallCost)/2.0;
			target = "rozmów";
			break;
		case 1:
			playCost = (bestPrices[1] + minimalPlayCallCost)/2.0;
			target = "rozmów do play";
			break;
		case 2:
			insideCost = (bestPrices[2] + minimalInsideCallCost)/2.0;
			target = "rozmów w sieci";
			break;
		case 3:
			regularSms = (bestPrices[3] + minimalSmsCost)/2.0;
			target = "smsów";
			break;
		case 4:
			insideSms = (bestPrices[4] + minimalInsideSmsCost)/2.0;
			target = "smsów w sieci";
			break;
		}
		
		ourPrices.setPrices(regularCost, insideCost, playCost, regularSms, insideSms);
		IO.operatorPrint(ourPrices.operatorName + " używa strategii specialised. Opuszcza cenę " + target + ".", IO.INFO);

		lastStrategy = "specialised " + target;
		return ourPrices;
	}
}
